//============================================================================
// Name        : HTMLParser.cpp
// Author      : Baggio sl
// Version     :
// Copyright   : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================

#include <iostream>
#include <cstdio>
#include "HTMLParser.h"
#include "SequencialReadPages.h"
#include "./dicionario/Aurelio.h"
#include "./dicionario/Hasher.h"
#include "./dicionario/Timer.h"
#include <list>
#include <fstream>
#include <time>
#include "ThreadFunctionDatabase.h"


using namespace std;

int main() {
	const int NUM_DOCS_PER_ITERATION = 5000;
	time_t inicio;
	time(&inicio);
	time_t anterior = inicio;
	time_t agora;

	ofstream estatistica ("estatistica.txt");
	estatistica << "Legenda: " << endl;
	estatistica << "Etapa 1: Leitura do arquivo e filtragem de texto " << endl;
	estatistica << "Etapa 2: Primeira passada do Aurelio " << endl;
	estatistica << "Etapa 3: Segunda passada do Aurelio " << endl;
	estatistica << "Etapa 4: Salvando minimapa " << endl;
	estatistica << "Etapa 5: Concluido loop - Criando tabelas" << endl;
	
	estatistica << "inicio: loops com " << NUM_DOCS_PER_ITERATION << " documentos." << inicio << endl;
	
//	HTMLParser h;
	Substituter s;
	SequencialReadPages srp;
	bool temMaisDocs = false;
	std::tr1::shared_ptr<Aurelio> aurelioBuarque = Aurelio::getInstance();
	
//	freopen("mcSuga.txt", "w", stdout);
//	FILE * arquivo = fopen ("/work/teste/abc.txt", "r");
//	try { long long
//	cout << h.extractText("comeco <script> blah <script> blah2 </script> blah3 </script> fim! - outro <script> fd </script> aa") << endl;
//	}
//	catch (...){
//		cout << "blah" << endl;
//	}
//	cout << "teste" << endl;
//	char * chr;
//	fgets(chr, 500, arquivo);
//	string str = chr;
//	cout << "0: " << chr[0] << endl;
////	cout << "str: " << str << endl;
//	cout << "converted: " << s.convertHtmlString(str) << endl;
////	cout << h.extractText("Yahoo! &nbsp; Mon Yahoo! &nbsp; Mail Recherche Web Ouvrir Session") << endl;
//	cin >> b;
	string texto[NUM_DOCS_PER_ITERATION];
	uint textIds[NUM_DOCS_PER_ITERATION];
	list <unsigned long long> * wordHashes[NUM_DOCS_PER_ITERATION];
	short j = 0;
	uint k = 0;
	srp.goBackToCheckpoint();
	
	
	pthread_t oddsParser;
	pthread_t evensParser;
	pthread_attr_t attr;
	size_t stacksize;
	
	do {
		
		uint contIter = 0;
		
		cout << "Criando tabela..." << endl;
		do{
			
					
			texto[j] = srp.getPageHTML();
			textIds[j] = srp.htmlDocID();
			
			contIter++;
			
			j = (j+1)%NUM_DOCS_PER_ITERATION;
			temMaisDocs = srp.next();
			
		}while(j != 0 && temMaisDocs);
		
		
		
		cout << "Parsing..." << endl;
		
//		pthread_attr_init(&attr);
//		stacksize = Config::getQueueThreadStackSize();
//		pthread_attr_setstacksize (&attr, stacksize);
	

		ThreadFunctionDatabase::setContIter(contIter);
		
		uint rc;
		

		time(&agora);
		estatistica << "Etapa 1: " << agora-anterior << " acumulado: " << agora-inicio << endl;
		anterior = agora;
		
		cout << "ID inicial: " << textIds[0]  << endl;
		
		rc = pthread_create(&oddsParser, NULL, ThreadFunctionDatabase::parseOdds, (void *)texto); 
    	if (rc){
    		cout << "ERROR1; return code from pthread_create() is " << rc << "\n";
    		exit(-1);
    	}
    	
    	rc = pthread_create(&evensParser, NULL, ThreadFunctionDatabase::parseEvens, (void *)texto); 
    	if (rc){
    		cout << "ERROR2; return code from pthread_create() is " << rc << "\n";
    		exit(-1);
    	}
		
    	void * semFuncao;
    	
    	rc = pthread_join(oddsParser, &semFuncao);
    	if (rc){
    		printf("ERROR1; return code from pthread_join() is %d\n", rc);
    		exit(-1);
    	}

    	cout << "Odds end" << endl;
    	
    	rc = pthread_join(evensParser, &semFuncao);
    	if (rc){
    		printf("ERROR2; return code from pthread_join() is %d\n", rc);
    		exit(-1);
    	}

    	cout << "Evens end" << endl;

		
//		for(uint ii=0; ii < contInter; ii++) {
//			if (ii==0) {
//				time(&agora);
//				estatistica << "Etapa 1: " << agora-anterior << " acumulado: " << agora-inicio << endl;
//				anterior = agora;
//			}
//			if (ii % 473 == 29) {
//				cout << "j: " << ii << endl;
//				cout << "ID: " << hex << textIds[ii] << dec << endl;				
//			}
//			texto[ii] = h.extractText(texto[ii]);
//		}
		

		
		
		
		
		if (j == 0 || !temMaisDocs) {
			cout << "Entrei: "<< endl;
			
//			h.coutStatistics();
			time(&agora);
			estatistica << "Etapa 2: " << agora-anterior << " acumulado: " << agora-inicio << endl;
			anterior = agora;
			
			for (int i = 0; i < contIter; i++) {
//				cout << "BLAH1: " << i << " " << texto[i].size() << endl;
				if (texto[i] != "") {
					wordHashes[i] = aurelioBuarque->updateDictionarySizes(texto[i], textIds[i]);
					texto[i].clear();
				}
				else
					wordHashes[i] = NULL;
			}
//			aurelioBuarque->printDictionary();
			cout << "meio: " << endl;
			
			time(&agora);
			estatistica << "Etapa 3: " << agora-anterior << " acumulado: " << agora-inicio << endl;
			anterior = agora;
			
			aurelioBuarque->initializeVectors();
			cout << "meio2" << endl;
			for (int i = 0; i < contIter; i++) {
//				cout << "BLAH2: " << i << " " << texto[i].size() << endl;
				aurelioBuarque->updateDictionary(textIds[i], wordHashes[i]);
			}
			cout << "cabei!!!" << endl;
			
			time(&agora);
			estatistica << "Etapa 4: " << agora-anterior << " acumulado: " << agora-inicio << endl;
			anterior = agora;
			
			aurelioBuarque->printFullDictionaryInfo();
			cout << k++ << endl;
			cout << "Gravando minimapa..." << endl;
			aurelioBuarque->saveAndClear();
			cout << "Terminei de gravar!!!" << endl;
			
			time(&agora);
			estatistica << "Etapa 5: " << agora-anterior << " acumulado: " << agora-inicio << endl;
			anterior = agora;
			
			srp.setCheckpoint();
			if (!temMaisDocs)
				break;
		}
	} while (true);
	
//	cout << h.extractText("comeco <head> aki </head> outro <head> mais um </head>a fim! ") << endl;
//	cout << h.extractText("comeco a <tag nao> b <tag sim /  > c </tag nao> d ") << endl;
//	cout << h.extractText("fico de fora <body> Opa, tou dentro <tb estarei fora /> </body> tb fora, chuif") << endl;
//	cout << h.extractText("comeco <script> blah1 <script> blah2 </script> blah3 </script> blah4 <script> blah5 </script> fim!") << endl;
//	cout << h.extractText("comeco <style> blahh1 <style> blahh2 </style> blah3 </style> blahh4 <script> blahh5 </script> fim!") << endl;
//	cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!!
		return 0;
	
	
//------------------------******************************----------------------------------------
	
	
//	std::tr1::shared_ptr<Aurelio> aurelioBuarque = Aurelio::getInstance();
//	string texto[5];
//	list<unsigned long long> * wordHashes[5];
//	texto[0] = "para cada rosa uma rosa eh uma rosa";
//	texto[1] = "o cravo brigou com a rosa debaixo de uma sacada";
//	texto[2] = "um ex cravo para cada escravo";
//	texto[3] = "sacada a arma desfez se a rosa";
//	texto[4] = "briosa e manhosa a rosa desfez se alterosa";
//	for (int i = 0; i < 5; i++) {
//		wordHashes[i] = aurelioBuarque->updateDictionarySizes(texto[i], i);
//	}
////	aurelioBuarque->printDictionary();
//
//	aurelioBuarque->initializeVectors();
//	for (int i = 0; i < 5; i++) {
//		cout << "BLAH" << i << endl;
//		aurelioBuarque->updateDictionary(i, wordHashes[i]);
//	}
//	aurelioBuarque->printFullDictionary();
//		
//	//	cout << Hasher::abcHash("desfez") << endl;
//	//	cout << Hasher::abcHash("z") << endl;
//	//	cout << Hasher::reverseAbcHash(Hasher::abcHash("desfez")) << endl;
//	//	cout << Hasher::reverseAbcHash(Hasher::abcHash("z")) << endl;
//		
//	
//	
//	return 0;
	
	
	//------------------------******************************----------------------------------------
//	string mcSuga1 = "mcSuga1";
//	double dummy[500];
//	string mcSuga2 = "mcSuga2";
//
//	cout << "1: " << Hasher::abcHash(mcSuga1) << endl;
//	cout << "2: " << Hasher::abcHash(mcSuga2) << endl;
//	
//	mcSuga1 = "mcSuga2";
//	mcSuga2 = "mcSuga1";
//	cout << "1: " << Hasher::abcHash(mcSuga1) << endl;
//	cout << "2: " << Hasher::abcHash(mcSuga2) << endl;
//	
//	return 0;
		

	//------------------------******************************----------------------------------------
//	
//	Timer t;
//    	  
//	t.begin();
//	double i;
//    	  for (i = 0; i < 500000000; i+=1) {
//    		  uint b = 7;
//    	  }
//
//    t.end();
//    cout << "diff: " << t.diff() << endl; 
//    	  
	//------------------------******************************----------------------------------------
	
	
//	HTMLParser h;
//	
////	cout << h.extractText("teste <b><mc <suga> <olha eu <o/> /> <ab> /mc> <b></b> <!-- suga --><tag com /> b <tag sem > c </tag sem> g </b>d<tag com 2 /> abc");
//	string s = "a <t<script>ag2>\n<script t blha> <script MC suga> MCSuga </script>  fds gwerui dfksj </script> b </script> c";
//	cout << s << endl;
//	h.removeScripts(s);
//	cout << s << endl;
//	
//	
//	return 0;
}
